package outbound_task

import (
	"context"
	"encoding/json"
	"errors"
	"git.mycaigou.com/gfyx/micro-gfyx-api/infrastructure/common/constants"
	dto "git.mycaigou.com/gfyx/micro-gfyx-api/infrastructure/dto/market"
	"git.mycaigou.com/gfyx/micro-gfyx-api/infrastructure/repository/market"
	"git.mycaigou.com/gfyx/micro-gfyx-api/infrastructure/utils"
	pb "git.mycaigou.com/gfyx/micro-gfyx-api/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/market"
	"git.myscrm.cn/golang/stark/v4"
)

type outboundTaskService struct {
	outboundTaskRepo market.OutboundTaskRepositoryIface
}

func NewOutboundTaskService(
	outboundTaskRepo market.OutboundTaskRepositoryIface,
) OutboundTaskServiceIface {
	return &outboundTaskService{
		outboundTaskRepo: outboundTaskRepo,
	}
}

func (s *outboundTaskService) ImportCrowd(ctx context.Context, request *dto.TaskImportCrowdRequest) error {
	return s.outboundTaskRepo.ImportCrowd(ctx, request)
}

func (s *outboundTaskService) HandleOutboundTaskCallback(ctx context.Context, callbackData *dto.CallBackData) error {
	if callbackData == nil || callbackData.CallInstance == nil {
		return errors.New("CallInstance参数为空")
	}
	req := &pb.CallbackRequest{
		CompanyId:      callbackData.CallInstance.CompanyId,
		TaskId:         callbackData.CallInstance.CallJobId,
		CallInstanceId: callbackData.CallInstance.CallInstanceId,
		Duration:       callbackData.CallInstance.Duration,
		ChatRound:      callbackData.CallInstance.ChatRound,
		FinishStatus:   callbackData.CallInstance.FinishStatus,
		StartTime:      callbackData.CallInstance.StartTime,
		EndTime:        callbackData.CallInstance.EndTime,
		AuditUrl:       callbackData.CallInstance.LuyinOssUrl,
		HangUp:         callbackData.CallInstance.HangUp,
	}
	if callbackData != nil && callbackData.CallInstance != nil && callbackData.CallInstance.Properties != nil {
		var ok bool
		req.CompanyName, ok = callbackData.CallInstance.Properties["客户名称"].(string)
		if !ok {
			return errors.New("客户名称不存在")
		}
		req.Mobile, ok = callbackData.CallInstance.Properties["联系方式"].(string)
		if !ok {
			return errors.New("联系方式不存在")
		}
	} else {
		return errors.New("客户名称和联系方式不存在")
	}

	if len(callbackData.TaskResult) > 0 {
		for _, taskResult := range callbackData.TaskResult {
			if taskResult.ResultName == "客户意向等级" {
				req.Intention = taskResult.ResultValue
				break
			}
		}
	}

	if len(callbackData.PhoneLogs) > 0 {
		bytes, _ := json.Marshal(callbackData.PhoneLogs)
		req.PhoneLogs = string(bytes)
	}

	if len(callbackData.CallRepeat) > 0 {
		req.LineName = callbackData.CallRepeat[0].CallerPhone
	}

	return s.outboundTaskRepo.HandleOutboundTaskCallback(ctx, req)
}

func (s *outboundTaskService) GetOutboundClueList(ctx context.Context, request *dto.GetOutboundClueListRequest) (*dto.GetOutboundClueListResponse, error) {
	if request == nil {
		return nil, errors.New("request参数为空")
	}
	pbRequest := &pb.GetOutboundClueListRequest{
		Keyword:      request.Keyword,
		TaskId:       request.TaskId,
		Intention:    request.Intention,
		DurationMin:  request.DurationMin,
		DurationMax:  request.DurationMax,
		ChatRoundMin: request.ChatRoundMin,
		ChatRoundMax: request.ChatRoundMax,
		FinishStatus: request.FinishStatus,
		StartDate:    request.StartDate,
		EndDate:      request.EndDate,
		AuditStatus:  request.AuditStatus,
		Page:         request.Page,
		PageSize:     request.PageSize,
	}
	if pbRequest.PageSize == 0 {
		pbRequest.PageSize = 20
	}
	if pbRequest.Page == 0 {
		pbRequest.Page = 1
	}
	pbResp, err := s.outboundTaskRepo.GetOutboundClueList(ctx, pbRequest)
	if err != nil {
		return nil, err
	}

	response := &dto.GetOutboundClueListResponse{
		Total: 0,
		List:  []*dto.OutboundClueData{},
	}

	if pbResp == nil {
		return response, nil
	}

	response.Total = pbResp.Total
	for _, item := range pbResp.List {
		response.List = append(response.List, &dto.OutboundClueData{
			Id:                 item.Id,
			CompanyName:        item.CompanyName,
			CallInstanceId:     item.CallInstanceId,
			Mobile:             item.Mobile,
			Duration:           item.Duration,
			ChatRound:          item.ChatRound,
			FinishStatus:       item.FinishStatus,
			FinishStatusRemark: constants.GetFinishStatusRemark(item.FinishStatus),
			Intention:          item.Intention,
			IntentionRemark:    constants.GetIntentionRemark(item.Intention),
			StartTime:          item.StartTime,
			EndTime:            item.EndTime,
			TaskId:             item.TaskId,
			IsRead:             item.IsRead,
			AuditStatus:        item.AuditStatus,
			TenantCode:         request.TenantCode,
			TaskName:           item.TaskName,
			RccProjectName:     item.RccProjectName,
		})
	}
	return response, nil
}

func (s *outboundTaskService) GetOutboundClueDetail(ctx context.Context, request *dto.GetOutboundClueDetailRequest) (*dto.GetOutboundClueDetailResponse, error) {
	if request == nil {
		return nil, errors.New("request参数为空")
	}
	resp, err := s.outboundTaskRepo.GetOutboundClueDetail(ctx, &pb.GetOutboundClueDetailRequest{
		CallInstanceId: request.CallInstanceId,
		TaskId:         request.TaskId,
		Mobile:         request.Mobile,
	})
	if err != nil {
		return nil, err
	}
	result := &dto.GetOutboundClueDetailResponse{
		List: []*dto.OutboundClueDetail{},
	}
	if resp != nil {
		for _, itemPb := range resp.List {
			itemDto := &dto.OutboundClueDetail{
				CompanyName:     itemPb.CompanyName,
				Mobile:          itemPb.Mobile,
				Intention:       itemPb.Intention,
				IntentionRemark: constants.GetIntentionRemark(itemPb.Intention),
				AuditUrl:        itemPb.AuditUrl,
				Duration:        itemPb.Duration,
				ChatRound:       itemPb.ChatRound,
				HangUp:          itemPb.HangUp,
				StartTime:       itemPb.StartTime,
				PhoneLogs:       []*dto.ClueDetailPhoneLog{},
				AuditRemark:     itemPb.AuditRemark,
			}
			for _, phoneLog := range itemPb.PhoneLogs {
				itemDto.PhoneLogs = append(itemDto.PhoneLogs, &dto.ClueDetailPhoneLog{
					Speaker:   phoneLog.Speaker,
					StartTime: phoneLog.StartTime,
					EndTime:   phoneLog.EndTime,
					Content:   phoneLog.Content,
				})
			}
			result.List = append(result.List, itemDto)
		}
	}

	// 设置消息已读
	_, err = s.outboundTaskRepo.SetTaskLogRead(ctx, &pb.SetTaskLogReadRequest{
		CallInstanceId: request.CallInstanceId,
	})
	if err != nil {
		return result, err
	}

	return result, nil
}

func (s *outboundTaskService) ExportTaskLog(ctx context.Context, request *dto.OutboundClueExportRequest) (*dto.ExcelExportResponse, error) {
	resp, err := s.outboundTaskRepo.ExportTaskLog(ctx, &pb.ExportTaskLogRequest{
		Ids:          request.Ids,
		Keyword:      request.Keyword,
		TaskId:       request.TaskId,
		Intention:    request.Intention,
		DurationMin:  request.DurationMin,
		DurationMax:  request.DurationMax,
		ChatRoundMin: request.ChatRoundMin,
		ChatRoundMax: request.ChatRoundMax,
		FinishStatus: request.FinishStatus,
		StartDate:    request.StartDate,
		EndDate:      request.EndDate,
	})
	if err != nil {
		return nil, err
	}
	if resp == nil {
		return nil, errors.New("导出失败")
	}
	result := &dto.ExcelExportResponse{
		FileUrl: resp.FileUrl,
	}
	return result, nil
}

func (s *outboundTaskService) CreateTask(ctx context.Context, companyId int64, userId int64, request *dto.CreateTaskRequest) (*dto.CreateTaskResponse, error) {
	params := &pb.CreateTaskRequest{
		TaskName:         request.TaskName,
		TaskType:         request.TaskType,
		StartDate:        request.StartDate,
		RobotDefId:       request.RobotDefId,
		UserPhoneIds:     request.UserPhoneIds,
		ConcurrencyQuota: request.ConcurrencyQuota,
		RepeatCallCnt:    request.RepeatCallCnt,
		PushUserIds:      request.PushUserIds,
		CompanyId:        companyId,
		UserId:           userId,
	}
	createTaskResponse, err := s.outboundTaskRepo.CreateTask(ctx, params)
	if err != nil {
		stark.Logger.Errorf(ctx, "CreateTask error, request: %+v, err:%+v", request, err)
		return nil, err
	}
	return &dto.CreateTaskResponse{
		TaskId: createTaskResponse.TaskId,
	}, nil
}

func (s *outboundTaskService) UpdateTask(ctx context.Context, companyId int64, userId int64, request *dto.UpdateTaskRequest) (*dto.UpdateTaskResponse, error) {
	params := &pb.UpdateTaskRequest{
		TaskId:           request.TaskId,
		TaskName:         request.TaskName,
		TaskType:         request.TaskType,
		StartDate:        request.StartDate,
		RobotDefId:       request.RobotDefId,
		UserPhoneIds:     request.UserPhoneIds,
		ConcurrencyQuota: request.ConcurrencyQuota,
		RepeatCallCnt:    request.RepeatCallCnt,
		PushUserIds:      request.PushUserIds,
		CompanyId:        companyId,
		UserId:           userId,
	}
	_, err := s.outboundTaskRepo.UpdateTask(ctx, params)
	if err != nil {
		stark.Logger.Errorf(ctx, "UpdateTask error, request: %+v, err:%+v", request, err)
		return nil, err
	}
	return &dto.UpdateTaskResponse{
		IsSucceed: true,
	}, nil
}

func (s *outboundTaskService) UpdateIntention(ctx context.Context, request *dto.UpdateIntentionRequest) (*dto.UpdateIntentionResponse, error) {
	params := &pb.UpdateIntentionRequest{
		CallInstanceId: request.CallInstanceId,
		Intention:      request.Intention,
	}
	_, err := s.outboundTaskRepo.UpdateIntention(ctx, params)
	if err != nil {
		stark.Logger.Errorf(ctx, "UpdateIntention error, request: %+v, err:%+v", request, err)
		return nil, err
	}
	return &dto.UpdateIntentionResponse{
		IsSucceed: true,
	}, nil
}

func (s *outboundTaskService) DeleteTask(ctx context.Context, companyId int64, userId int64, request *dto.DeleteTaskRequest) (*dto.DeleteTaskResponse, error) {
	params := &pb.DeleteTaskRequest{
		TaskId:    request.TaskId,
		CompanyId: companyId,
		UserId:    userId,
	}
	_, err := s.outboundTaskRepo.DeleteTask(ctx, params)
	if err != nil {
		stark.Logger.Errorf(ctx, "DeleteTask error, request: %+v, err:%+v", request, err)
		return nil, err
	}
	return &dto.DeleteTaskResponse{
		IsSucceed: true,
	}, nil
}

func (s *outboundTaskService) ExecuteTask(ctx context.Context, companyId int64, userId int64, request *dto.ExecuteTaskRequest) (*dto.ExecuteTaskResponse, error) {
	taskIds := make([]int64, 0)
	if request.TaskId != 0 {
		taskIds = append(taskIds, request.TaskId)
	}
	params := &pb.ExecuteTaskRequest{
		TaskIds:   taskIds,
		Command:   request.Command,
		CompanyId: companyId,
		UserId:    userId,
	}
	_, err := s.outboundTaskRepo.ExecuteTask(ctx, params)
	if err != nil {
		stark.Logger.Errorf(ctx, "ExecuteTask error, request: %+v, err:%+v", request, err)
		return nil, err
	}
	return &dto.ExecuteTaskResponse{
		IsSucceed: true,
	}, nil
}

// GetTaskList 获取任务列表
func (s *outboundTaskService) GetTaskList(ctx context.Context, companyId int64, userId int64, request *dto.GetTaskListRequest) (*dto.GetTaskListResponse, error) {
	params := &pb.GetTaskListRequest{
		CreateDate: request.CreateDate,
		EndDate:    request.EndDate,
		Page:       request.Page,
		PageSize:   request.PageSize,
		TaskName:   request.TaskName,
		CompanyId:  companyId,
	}
	remoteResponse, err := s.outboundTaskRepo.GetTaskList(ctx, params)
	if err != nil {
		stark.Logger.Errorf(ctx, "GetTaskList error, userId: %d, request: %+v, err:%+v", userId, request, err)
		return nil, err
	}

	response := &dto.GetTaskListResponse{
		Total: remoteResponse.Total,
		List:  make([]*dto.ItemOfTaskList, 0),
	}

	for _, itemPb := range remoteResponse.List {
		response.List = append(response.List, &dto.ItemOfTaskList{
			TaskId:     itemPb.TaskId,
			TaskName:   itemPb.TaskName,
			TaskStatus: itemPb.TaskStatus,
			SeatNum:    itemPb.SeatNum,
			CreatedBy:  itemPb.CreatedBy,
			CreatedOn:  itemPb.CreatedOn,
			TotalCount: itemPb.TotalCount,
			DoneCount:  itemPb.DoneCount,
		})
	}
	return response, nil
}

// GetTaskDetail 获取任务详情
func (s *outboundTaskService) GetTaskDetail(ctx context.Context, companyId int64, userId int64, request *dto.GetTaskDetailRequest) (*dto.GetTaskDetailResponse, error) {
	params := &pb.GetTaskDetailRequest{
		TaskId:    request.TaskId,
		CompanyId: companyId,
	}
	remoteResponse, err := s.outboundTaskRepo.GetTaskDetail(ctx, params)
	if err != nil {
		stark.Logger.Errorf(ctx, "GetTaskDetail error, userId: %d, request: %+v, err:%+v", userId, request, err)
		return nil, err
	}
	response := &dto.GetTaskDetailResponse{
		TaskId:             remoteResponse.TaskId,
		TaskName:           remoteResponse.TaskName,
		TaskType:           remoteResponse.TaskType,
		TaskStatus:         remoteResponse.TaskStatus,
		RobotDefName:       remoteResponse.RobotDefName,
		SeatNum:            remoteResponse.SeatNum,
		CallPhones:         remoteResponse.CallPhones,
		TotalCount:         remoteResponse.TotalCount,
		CalledCount:        remoteResponse.CalledCount,
		UnavailableCount:   remoteResponse.UnavailableCount,
		IntentionCount:     remoteResponse.IntentionCount,
		CallCompletionRate: remoteResponse.CallCompletionRate,
		IntentionRate:      remoteResponse.IntentionRate,
		StartDate:          remoteResponse.StartDate,
		RobotDefId:         remoteResponse.RobotDefId,
		UserPhoneIds:       remoteResponse.UserPhoneIds,
		ConcurrencyQuota:   remoteResponse.ConcurrencyQuota,
		RepeatCallCnt:      remoteResponse.RepeatCallCnt,
		PushUserIds:        remoteResponse.PushUserIds,
	}
	return response, nil
}

// GetUnStartCallList 获取未开始的任务列表
func (s *outboundTaskService) GetUnStartCallList(ctx context.Context, companyId int64, userId int64, request *dto.GetUnStartCallListRequest) (*dto.GetUnStartCallListResponse, error) {
	params := &pb.GetUnStartCallListRequest{
		TaskId:    request.TaskId,
		CompanyId: companyId,
		Page:      request.Page,
		PageSize:  request.PageSize,
	}
	remoteResponse, err := s.outboundTaskRepo.GetUnStartCallList(ctx, params)
	if err != nil {
		stark.Logger.Errorf(ctx, "GetUnStartCallList error, userId: %d, request: %+v, err:%+v", userId, request, err)
		return nil, err
	}
	response := &dto.GetUnStartCallListResponse{
		Total: remoteResponse.Total,
		List:  make([]*dto.ItemOfUnStartCallList, 0),
	}

	for _, itemPb := range remoteResponse.List {
		response.List = append(response.List, &dto.ItemOfUnStartCallList{
			CallInstanceId:    itemPb.CallInstanceId,
			CustomerName:      itemPb.CustomerName,
			CustomerTelephone: utils.GetMobileEncrypt(itemPb.CustomerTelephone),
		})
	}

	return response, nil
}

func (s *outboundTaskService) AuditOutboundClue(ctx context.Context, request *dto.AuditOutboundClueRequest) error {

	requestPb := &pb.AuditOutboundClueRequest{
		Id:            request.Id,
		Intention:     request.Intention,
		AuditStatus:   0,
		AuditRemark:   request.AuditRemark,
		AuditUserName: request.AuditUserName,
	}
	resp, err := s.outboundTaskRepo.AuditOutboundClue(ctx, requestPb)
	if err != nil {
		return nil
	}
	if resp == nil || !resp.IsSucceed {
		return errors.New("审核失败")
	}
	return nil
}
